package cn.zl.GB28181.storage.impl;

import cn.hutool.core.util.StrUtil;
import cn.zl.GB28181.cache.DeviceCache;
import cn.zl.GB28181.core.DeviceChannelDataHandle;
import cn.zl.GB28181.core.ErrorCallback;
import cn.zl.GB28181.core.SSRCInfo;
import cn.zl.GB28181.storage.IDeviceChannelStorage;
import cn.zl.GB28181.transmit.cmd.ISIPCommander;
import cn.zl.ZLM.service.IZLMService;
import cn.yunbamboos.exception.AppException;
import cn.zl.config.ZLConfig;
import cn.zl.mapper.DeviceChannelMapper;
import cn.zl.model.Device;
import cn.zl.model.DeviceChannel;
import jakarta.annotation.Resource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.stereotype.Component;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;
import org.springframework.util.CollectionUtils;

import java.util.List;
import java.util.Optional;

@Component
public class DeviceChannelStorageImpl implements IDeviceChannelStorage {

    private static final Logger logger = LoggerFactory.getLogger(DeviceChannelStorageImpl.class);

    @Resource
    private ZLConfig config;
    @Resource
    private DeviceCache deviceCache;
    @Resource
    private DeviceChannelMapper deviceChannelMapper;
    @Resource
    private DataSourceTransactionManager dataSourceTransactionManager;
    @Resource
    private DefaultTransactionDefinition transactionDefinition;
    @Resource
    private IZLMService zlmService;
    @Resource
    private ISIPCommander sipCommander;

    @Override
    public void cleanChannelsForDevice(String deviceId) {
        deviceChannelMapper.cleanChannelsByDeviceId(deviceId);
    }

    @SuppressWarnings("DuplicatedCode")
    @Override
    public boolean resetChannels(String deviceId, List<DeviceChannel> deviceChannelList) {
        if (CollectionUtils.isEmpty(deviceChannelList)) {
            return false;
        }
        DeviceChannelDataHandle handle = new DeviceChannelDataHandle();
        // 当前设备下所有的通道
        handle.setAllChannelMap(deviceChannelMapper.queryAllChannelsByDeviceId(deviceId));
        handle.setDeviceChannelList(deviceChannelList);
        List<DeviceChannel> channels = handle.getChannels();
        if (CollectionUtils.isEmpty(channels)) {
            return false;
        }
        // 开启事务
        transactionDefinition.setReadOnly(false);
        TransactionStatus transactionStatus = dataSourceTransactionManager.getTransaction(transactionDefinition);
        try {
            // 需要新增列表
            List<DeviceChannel> addChannels = handle.getAddChannels();
            // 需要更新列表
            List<DeviceChannel> updateChannels = handle.getUpdateChannels();
            // 需要删除列表
            List<DeviceChannel> deleteChannels = handle.getDeleteChannels();

            boolean result = false;
            if (!addChannels.isEmpty()) {
                result = deviceChannelMapper.batchInsert(addChannels) < 0;
            }
            if (!result && !updateChannels.isEmpty()) {
                result = deviceChannelMapper.batchUpdate(updateChannels) < 0;
            }
            if (!result && !deleteChannels.isEmpty()) {
                result = deviceChannelMapper.batchDelete(deviceChannelList) < 0;
            }
            if (result) {
                //事务回滚
                dataSourceTransactionManager.rollback(transactionStatus);
            }
            dataSourceTransactionManager.commit(transactionStatus);     //手动提交
            return true;
        } catch (Exception e) {
            logger.error("未处理的异常 ", e);
            dataSourceTransactionManager.rollback(transactionStatus);
            return false;
        }
    }

    @SuppressWarnings("DuplicatedCode")
    @Override
    public boolean updateChannels(String deviceId, List<DeviceChannel> deviceChannelList) {
        if (CollectionUtils.isEmpty(deviceChannelList)) {
            return false;
        }
        DeviceChannelDataHandle data = new DeviceChannelDataHandle();
        // 当前设备下所有的通道
        data.setAllChannelMap(deviceChannelMapper.queryAllChannelsByDeviceId(deviceId));
        data.setDeviceChannelList(deviceChannelList);
        List<DeviceChannel> channels = data.getChannels();
        if (CollectionUtils.isEmpty(channels)) {
            return false;
        }

        transactionDefinition.setReadOnly(false);
        TransactionStatus transactionStatus = dataSourceTransactionManager.getTransaction(transactionDefinition);
        try {
            // 需要新增列表
            List<DeviceChannel> addChannels = data.getAddChannels();
            // 需要更新列表
            List<DeviceChannel> updateChannels = data.getUpdateChannels();

            boolean result = false;
            if (!addChannels.isEmpty()) {
                result = deviceChannelMapper.batchInsert(addChannels) < 0;
            }
            if (!result && !updateChannels.isEmpty()) {
                result = deviceChannelMapper.batchUpdate(updateChannels) < 0;
            }
            if (result) {
                //事务回滚
                dataSourceTransactionManager.rollback(transactionStatus);
            }
            dataSourceTransactionManager.commit(transactionStatus);     //手动提交
            return true;
        } catch (Exception e) {
            logger.error("未处理的异常 ", e);
            dataSourceTransactionManager.rollback(transactionStatus);
            return false;
        }
    }

    @Override
    public void play(String deviceId, String channelId, ErrorCallback<Object> callback) {
        Device device = deviceCache.get(deviceId);
        if (device == null) {
            logger.warn("[点播] 设备 deviceId: {} 不在线", deviceId);
            callback.run(500, "设备 deviceId: " + deviceId + " 不在线", null);
            return;
        }
//        if (device.getStreamMode().equalsIgnoreCase("TCP-ACTIVE") && !config.isRtpEnable()) {
//            logger.warn("[点播] 单端口收流时不支持TCP主动方式收流 deviceId: {},channelId:{}", deviceId, channelId);
//            callback.run(500, "单端口收流时不支持TCP主动方式收流", null);
//            return;
//        }
        Optional<DeviceChannel> channelOptional = deviceChannelMapper.queryByDeviceIdAndChannelId(deviceId, channelId);
        if (channelOptional.isEmpty()) {
            logger.warn("[点播] 未找到通道 deviceId: {},channelId:{}", deviceId, channelId);
            callback.run(500, "未找到通道", null);
            return;
        }
        DeviceChannel channel = channelOptional.get();
        try {
            // 打开RTP服务
            String streamId = StrUtil.format("{}_{}", deviceId, channelId);
            SSRCInfo ssrcInfo = zlmService.openRTPServer(streamId, 1, false);
            if (ssrcInfo == null) {
                callback.run(500, "无可用资源播放视频", null);
                return;
            }
            logger.info("[点播开始] deviceId: {}, channelId: {}, 码流类型：{}, 收流端口： {}, 码流：{}, 收流模式：{}, SSRC: {}, SSRC校验：{}",
                    device.getDeviceId(), channel.getChannelId(), channel.getStreamIdentification(),
                    ssrcInfo.getPort(), ssrcInfo.getStream(), device.getStreamMode(), ssrcInfo.getSsrc(), device.isSsrcCheck());

            sipCommander.playStreamCmd(ssrcInfo, device, channel, null, null);
        } catch (Exception e) {
            if (e instanceof AppException exception) {
                callback.run(500, exception.getMsg(), null);
                return;
            } else {

                throw AppException.c("点播异常 {}", e.getMessage());
            }
        }
    }
}
